# coding:utf-8 
import random
from datetime import datetime
from typing import Optional, Union, NamedTuple, List, Dict, Tuple

from faker import Faker
from sqlmodel import SQLModel, Field, select, create_engine
from sqlalchemy.engine import Engine
from sqlalchemy.exc import SQLAlchemyError

if __name__ == '__main__':
    from config import TZ_shanghai, RoleEnum, PermissionEnum
else:
    from .config import TZ_shanghai, RoleEnum, PermissionEnum

HOST        = "106.54.236.158"
PORT        = 9998
USER        = "root"
PASSWORD    = "123456"
DATABASE    = "libraryms"
DATABASE_URL = f'mysql://{USER}:{PASSWORD}@{HOST}:{PORT}/{DATABASE}'
engine = create_engine(DATABASE_URL, echo=True)
# NOTE 最新创建session方法,不需要上下文管理session,但是需要close
from sqlalchemy.orm import sessionmaker
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
session_local = SessionLocal()



class BaseModel(SQLModel):
    """基类:id(主键) 创建时间 备注"""
    __tablename__ = "BaseModel"
    id            : int = Field(title="id", nullable=False, default=None, primary_key=True)
    create_time   : str = Field(title="创建时间", nullable=False, default=datetime.now(tz=TZ_shanghai).strftime("%Y-%m-%d %H:%M:%S"))
    note          : str = Field(title="备注", nullable=True, default='')

class BookInfo(BaseModel, table=True):
    """图书信息表"""
    __tablename__ = "bookinfos"
    title             : str = Field(title="书名", nullable=False)
    author            : str = Field(title="作者", nullable=False)
    isbn              : str = Field(title="ISBN", nullable=False)
    published_year    : int = Field(title="出版年份", nullable=False)

    def __hash__(self):
        # 根据 title 属性计算哈希值
        return hash(self.title)

    def __eq__(self, other):
        # 根据 title 属性判断两个对象是否相等
        if isinstance(other, BookInfo):
            return self.title == other.title and self.isbn == other.isbn
        return False

    def to_dict(self):
        return {
            "id": self.id,
            "create_time": self.create_time,
            "title": self.title,
            "author": self.author,
            "isbn": self.isbn,
            "published_year": self.published_year,
            "note": self.note,
        }

class Permission(BaseModel, table=True):
    """权限表"""
    __tablename__ = "permissions"
    permission: PermissionEnum = Field(title="权限", nullable=False)

class Role(BaseModel, table=True):
    """角色表"""
    __tablename__ = "roles"
    role: RoleEnum = Field(title="角色", nullable=False)

class User(BaseModel, table=True):
    """用户信息表"""
    __tablename__ = "users"
    username    : str   = Field(title="用户名", nullable=False)
    password    : str   = Field(title="密码", nullable=False)
    role        : RoleEnum  = Field(title="角色", nullable=False)



def PerssionsAndRoles():
    """初始化权限表和角色表数据"""
    sql_ = select(Permission)
    permissions = session_local.execute(sql_).all()
    if len(permissions) == 0:
        print(f"需要初始化权限表和角色表数据")
        try:
            for _enum in PermissionEnum:
                session_local.add(Permission(permission=_enum,note=_enum.value))
            for _enum in RoleEnum:
                session_local.add(Role(role=_enum,note=_enum.value))
            session_local.commit()
            print(f"初始化权限表和角色表数据成功")
        except SQLAlchemyError:
            session_local.rollback()
            print("数据库操作失败")
        finally:
            session_local.close()
    else:
        print(f"已经初始化过权限表和角色表数据")

def FakerBookinfos(count):
    """生成随机图书数据"""
    fake = Faker()
    def generate_random_isbn():
        """生成随机 ISBN"""
        return f"{random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(10000, 99999)}-{random.randint(0, 9)}"
    books = []
    for _ in range(count):
        book = BookInfo(
            title=fake.sentence(nb_words=4),  # 随机生成 4 个词的书名
            author=fake.name(),               # 随机生成作者名
            isbn=generate_random_isbn(),      # 随机生成 ISBN
            published_year=random.randint(1900, 2025)  # 随机生成出版年份
        )
        books.append(book)
    return books

def Bookinfos(count=100):
    """初始化图书信息表数据"""
    sql_ = select(BookInfo)
    bookinfos = session_local.execute(sql_).all()
    if len(bookinfos) == 0:
        try:
            bookinfos = FakerBookinfos(count)
            for bookinfo in bookinfos:
                session_local.add(bookinfo)
            session_local.commit()
            print(f"初始化图书信息表数据成功")
        except SQLAlchemyError:
            session_local.rollback()
            print("数据库操作失败")
        finally:
            session_local.close()
    else:
        print(f"已经初始化过图书信息表数据成功")

def Users():
    """初始化用户表数据(root和admin)"""
    sql_ = select(User)
    users:List[User] = session_local.execute(sql_).all()
    flag_root, flag_admin = False, False
    for user in users:
        if user[0].username == 'root' and user[0].role == RoleEnum.root:
            flag_root = True
        elif user[0].username == 'admin' and user[0].role == RoleEnum.admin:
            flag_admin = True
    def add(flag:bool,user_name='root' or 'admin'):
        """是否初始化用户root或admin"""
        if not flag:
            try:
                if user_name =='root':
                    user = User(username=RoleEnum.root.name,password=RoleEnum.root.name,role=RoleEnum.root)
                elif user_name =='admin':
                    user = User(username=RoleEnum.admin.name,password=RoleEnum.admin.name,role=RoleEnum.admin)
                session_local.add(user)
                session_local.commit()
                print(f"初始化用户{user_name}数据成功")
            except SQLAlchemyError:
                session_local.rollback()
                print("数据库操作失败")
            finally:
                session_local.close()
        else:
            print(f"已经初始化过初始化用户{user_name}数据")
    add(flag_root,'root')
    add(flag_admin,'admin')

def rebuild_all_table(engine:Engine):
    """重新建立所有表"""
    # 删除所有表
    SQLModel.metadata.drop_all(engine)
    # 创建所有表
    SQLModel.metadata.create_all(engine)

if __name__ == '__main__':
    rebuild_all_table(engine)
else:
    PerssionsAndRoles()
    Bookinfos()
    Users()


